package org.ccay.sitemap.service.impl;

import static org.ccay.core.util.DaoUtil.assertExists;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.ccay.core.exception.ApplicationException;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.log.ILogger;
import org.ccay.core.request.impl.RequestContext;
import org.ccay.core.util.CollectionUtil;
import org.ccay.core.util.StringUtil;
import org.ccay.security.authc.DefaultProgramAuthorizationInfo;
import org.ccay.security.entity.Permission;
import org.ccay.security.reaml.IPermissionMetadataScanner;
import org.ccay.security.reaml.Reaml;
import org.ccay.sitemap.SiteMapApplicationException;
import org.ccay.sitemap.SiteNodeSimpleVO;
import org.ccay.sitemap.SiteNodeVO;
import org.ccay.sitemap.dao.ISiteMapQueryDao;
import org.ccay.sitemap.service.ISiteMapQueryService;
import org.ccay.sitemap.service.impl.internal.SiteMapBuilder;
import org.springframework.cache.annotation.Cacheable;

/**
 * 暴露给其他模块
 * 用来获取用户角色的网站导航菜单栏	
 * @author chaowangbang
 * @since 2011-10-24
 */
@Named
public class SiteMapQueryService implements ISiteMapQueryService {
	
	private static final ILogger logger = CcayLoggerFactory.getLogger(ISiteMapQueryService.class); 
	
	@Inject
	private ISiteMapQueryDao iSiteMapDao;
	
	@Inject
	private SiteMapBuilder iSiteMapBuilder;
	
	@Inject 
	private Reaml realm;
	
	@Inject
	IPermissionMetadataScanner scanner;
	
	public SiteNodeSimpleVO findAuthorizedSiteMap() throws ApplicationException {
		SiteNodeVO fullMapRoot = findWholeSiteMap(RequestContext.getCurrent().getUserLanguage());
		return iSiteMapBuilder.buildRoleSiteMap(getCurrentUserPermissions(), fullMapRoot);
	}

	@Override
	@Cacheable(value=ISiteMapQueryService.SITE_MAP)
	public SiteNodeVO findWholeSiteMap(String language) throws ApplicationException {
		SiteNodeVO siteNodeVO = new SiteNodeVO();
		//只查询状态是发布的栏目
		siteNodeVO.setStatus("2");
		List<SiteNodeVO> allNodes;
		allNodes = iSiteMapDao.findSiteNodeList(siteNodeVO);
		return iSiteMapBuilder.buildWholeSiteMapByLanguage(allNodes, language);
	}
	
	// 获取用户权限
	private Set<String> getCurrentUserPermissions(){
		//权限列表
		if(null !=  RequestContext.getCurrent() && null != RequestContext.getCurrent().getUser()){
			PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
			DefaultProgramAuthorizationInfo authorizationInfo = (DefaultProgramAuthorizationInfo)realm.getCachedAuthorizationInfo(principals);
	        return new HashSet<String>(authorizationInfo.getStringPermissions());
		}
		return Collections.emptySet();
	}
	
	@Override
	@Cacheable(value=SITE_MAP,key="#siteNodeVO.siteNodeId")
	public SiteNodeVO findSiteNode(SiteNodeVO siteNodeVO)
			throws ApplicationException {
		SiteNodeVO existNode = iSiteMapDao.findSiteNode(siteNodeVO);
		return assertExists(existNode, SITE_MAP_NODE);
	}
	
	@Override
	@Cacheable(value=ISiteMapQueryService.SITE_MAP)
	public SiteNodeVO findOneSiteMapByParentId(String parentId) throws ApplicationException{
		logger.info("Getting one map for parent id :" + parentId);			
		
		if (StringUtil.isNullOrEmpty(parentId) || Integer.parseInt(parentId) == 0) {
			return findWholeSiteMap(RequestContext.getCurrent().getUserLanguage());
		} 
		
		SiteNodeVO siteNodeVO = new SiteNodeVO();
		//只查询状态是发布的栏目
		siteNodeVO.setStatus("2");
		siteNodeVO.setSiteNodeId(Integer.parseInt(parentId));
		List<SiteNodeVO> allNodes;
		allNodes = iSiteMapDao.findChildSiteNodeList(siteNodeVO);
		SiteNodeVO parentSiteNodeVO = findSiteNodeVOById(allNodes, siteNodeVO.getSiteNodeId());
		if (parentSiteNodeVO == null) {
			throw new SiteMapApplicationException("ccay.sitemap.00010005");
		}
		return iSiteMapBuilder.buildWholeSiteMap(allNodes, parentSiteNodeVO.getParent().getSiteNodeId());
	}
	
	private SiteNodeVO findSiteNodeVOById(List<SiteNodeVO> allNodes, int siteNodeId){
		if(CollectionUtil.isNullOrEmpty(allNodes)){
			return null;
		}
		for (SiteNodeVO siteNodeVO : allNodes) {
			if(siteNodeVO.getSiteNodeId() == siteNodeId){
				return siteNodeVO;
			}
		}
		return null;
	}
	
	@Override
	public List<SiteNodeVO> findSiteNodeTreeList(SiteNodeVO siteNodeVO)
			throws ApplicationException {
		List<SiteNodeVO> siteNodeList = iSiteMapDao.findSiteNodeTreeList(siteNodeVO);
		Set<Permission> permissions = findAllPermissionList();
		//设置权限名称
		for(SiteNodeVO siteNode :siteNodeList){
			if(StringUtil.isNullOrEmpty(siteNode.getPermissionString())){
				continue;
			}
			for(Permission p : permissions){
				if(p.getPermissionString().equals(siteNode.getPermissionString())){
					siteNode.setPermissionName(p.getResourceName()+":"+p.getOperationName());
				}
			}
		}
		return siteNodeList;
	}
	
	@Override
	@Cacheable(SITE_MAP)
	public int findCountSiteNode(SiteNodeVO siteNodeVO){
		return iSiteMapDao.findCountSiteNode(siteNodeVO);
	}
	
	private Set<Permission> findAllPermissionList(){
		return scanner.loadPermissionsMetadatas();
	}
}
